<?php

namespace wxpay;


use WeChatPay\Builder;
use WeChatPay\Crypto\AesGcm;
use WeChatPay\Crypto\Rsa;
use WeChatPay\Formatter;
use WeChatPay\Util\PemUtil;
use Yansongda\Pay\Log;

class Pay
{

// 设置参数

    // 商户号
    private $merchantId = "1678233381";
    private $appid = "wxde7c4c1de695c4ca";
    private $apiv3Key = "370CBDD333B2F3932B64D50BB80EDB0E";
    private $notify_url = "https://taochewa.com/api/epay/notifyx";

    // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
    private $merchantPrivateKeyFilePath;
    private $merchantPrivateKeyInstance;

    // 「商户API证书」的「证书序列号」
    private $merchantCertificateSerial;

    // 从本地文件中加载「微信支付平台证书」，用来验证微信支付应答的签名
    private $platformCertificateFilePath;
    private $platformPublicKeyInstance;

    // 从「微信支付平台证书」中获取「证书序列号」
    private $platformCertificateSerial;


    public function instance()
    {
        $p = "file://" . str_replace('\\', '/', dirname(dirname(dirname(__DIR__))));
        // 从本地文件中加载「商户API私钥」，「商户API私钥」会用来生成请求的签名
        $this->merchantPrivateKeyFilePath = file_get_contents($p . "/server/certificate/apiclient_key.pem");
        $this->merchantPrivateKeyInstance = Rsa::from($this->merchantPrivateKeyFilePath, Rsa::KEY_TYPE_PRIVATE);

        // 「商户API证书」的「证书序列号」
        $this->merchantCertificateSerial = '2B1D8A8E071B0BC801B3CF0A6248EFE3477176B3';

        // 从本地文件中加载「微信支付平台证书」，用来验证微信支付应答的签名
        $this->platformCertificateFilePath = file_get_contents($p . "/server/certificate/wechatpay_256D19274A2591B11CF281D3B7D4B90523182289.pem");

        $this->platformPublicKeyInstance = Rsa::from($this->platformCertificateFilePath, Rsa::KEY_TYPE_PUBLIC);
        // 从「微信支付平台证书」中获取「证书序列号」
        $this->platformCertificateSerial = PemUtil::parseCertificateSerialNo($this->platformCertificateFilePath);


        // 构造一个 APIv3 客户端实例
        $instance = Builder::factory([
            'mchid' => $this->merchantId,
            'serial' => $this->merchantCertificateSerial,
            'privateKey' => $this->merchantPrivateKeyInstance,
            'certs' => [
                $this->platformCertificateSerial => $this->platformPublicKeyInstance,
            ],
        ]);


        return $instance;
    }

    public function pay($total, $order_no, $openid, $title)
    {
        $instance = $this->instance();

        try {
            $resp = $instance
                ->chain('v3/pay/transactions/jsapi')
                ->post(['json' => [
                    'mchid' => $this->merchantId,
                    'out_trade_no' => $order_no,
                    'appid' => $this->appid,
                    'description' => $title,
                    'notify_url' => $this->notify_url,
                    'amount' => [
                        'total' => $total,
                        'currency' => 'CNY'
                    ],
                    'payer' => [
                        'openid' => $openid
                    ],
                ]]);
            $data["order_no"] = $order_no;
            $data["amount"] = $total;

            $getStatusCode = $resp->getStatusCode();
            $getBody = $resp->getBody();
            \think\Log::record("唤起支付：" . $getBody);

            $getBody = json_decode($getBody, true);
            $data["timeStamp"] = time();
            $data["nonceStr"] = time();
            $data["prepay_id"] = "prepay_id=" . $getBody["prepay_id"];
            $data["sign"] = $this->getWechartSign($this->appid, $data["timeStamp"], $data["nonceStr"], $data["prepay_id"]);
            return $data;
        } catch (\Exception $e) {
            $data["order_no"] = $order_no;
            $data["err"] = $e->getMessage();
            halt($e->getMessage());
            \think\Log::record("唤起支付-错误：" . json_encode($data));
            return false;
        }
    }


//调起支付的签名
    function getWechartSign($appid, $timeStamp, $noncestr, $prepay_id)
    {
        $str = $appid . "\n" . $timeStamp . "\n" . $noncestr . "\n" . $prepay_id . "\n";
        $p = "file://" . str_replace('\\', '/', dirname(dirname(dirname(__DIR__))));
        $key = file_get_contents($p . "/server/certificate/apiclient_key.pem");
        $str = $this->getSha256WithRSA($str, $key);
        return $str;
    }

    function getSha256WithRSA($content, $privateKey)
    {
        $binary_signature = "";
        $algo = "SHA256";
        openssl_sign($content, $binary_signature, $privateKey, $algo);
        $sign = base64_encode($binary_signature);
        return $sign;
    }

    public function notify()
    {
        $inBody = file_get_contents('php://input');;// 请根据实际情况获取，例如: file_get_contents('php://input');

        $apiv3Key = $this->apiv3Key;// 在商户平台上设置的APIv3密钥

        // 转换通知的JSON文本消息为PHP Array数组
        $inBodyArray = (array)json_decode($inBody, true);
        // 使用PHP7的数据解构语法，从Array中解构并赋值变量
        ['resource' => [
            'ciphertext' => $ciphertext,
            'nonce' => $nonce,
            'associated_data' => $aad
        ]] = $inBodyArray;
        // 加密文本消息解密
        $inBodyResource = AesGcm::decrypt($ciphertext, $apiv3Key, $nonce, $aad);
        Log::info("支付回调：" . $inBodyResource);
        // 把解密后的文本转换为PHP Array数组
        $inBodyResourceArray = (array)json_decode($inBodyResource, true);
        return $inBodyResourceArray;
    }


}


